home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / dakit / misca.asm < prev    next >
Encoding:
Assembly Source File  |  1990-10-12  |  18.4 KB  |  849 lines

  1. ;-----------------------------------------------------------------
  2. ; misca.asm
  3. ; ---------
  4. ; Miscellaneous minor assembly-language routines.
  5. ;-----------------------------------------------------------------
  6.  
  7.     include asm.inc
  8.     include main.inc
  9.     include ega.inc
  10.  
  11.     HEADER misca
  12.  
  13. ;-----------------------------------------------------------------
  14.  
  15. ; --- seg & offs of BIOS equipment flag word (we only use its lower byte)
  16. EQUIP_SEG    equ 40h
  17. EQUIP_OFFS    equ 10h
  18.  
  19.     DSEG
  20.  
  21. ; --- Most recent i/o error code.  NOTE: if there was not an error,
  22. ;     this is undefined.
  23.     public    _ioError
  24. _ioError dw    0
  25.  
  26. ; --- used by shift_right
  27.     public right_shift_masks
  28. right_shift_masks equ this word
  29.     db 11111111b, 11111111b
  30.     db 01111111b, 11111111b
  31.     db 00111111b, 11111111b
  32.     db 00011111b, 11111111b
  33.     db 00001111b, 11111111b
  34.     db 00000111b, 11111111b
  35.     db 00000011b, 11111111b
  36.     db 00000001b, 11111111b
  37.     db 00000000b, 11111111b
  38.     db 00000000b, 01111111b
  39.     db 00000000b, 00111111b
  40.     db 00000000b, 00011111b
  41.     db 00000000b, 00001111b
  42.     db 00000000b, 00000111b
  43.     db 00000000b, 00000011b
  44.     db 00000000b, 00000001b
  45.  
  46. ; --- used by shift_left
  47. left_shift_masks equ this word
  48.     db 11111111b, 11111111b
  49.     db 11111111b, 11111110b
  50.     db 11111111b, 11111100b
  51.     db 11111111b, 11111000b
  52.     db 11111111b, 11110000b
  53.     db 11111111b, 11100000b
  54.     db 11111111b, 11000000b
  55.     db 11111111b, 10000000b
  56.     db 11111111b, 00000000b
  57.     db 11111110b, 00000000b
  58.     db 11111100b, 00000000b
  59.     db 11111000b, 00000000b
  60.     db 11110000b, 00000000b
  61.     db 11100000b, 00000000b
  62.     db 11000000b, 00000000b
  63.     db 10000000b, 00000000b
  64.  
  65.     ENDDS
  66.  
  67. ;-----------------------------------------------------------------
  68.  
  69.     PSEG misca
  70.  
  71. ;-----------------------------------------------------------------
  72. ; WORD dataseg ();
  73. ; Returns the current value of the DS register.
  74. ;-----------------------------------------------------------------
  75.  
  76.     public _dataseg
  77.     STARTPROC _dataseg
  78.  
  79.     mov    ax,ds
  80.     ret
  81.  
  82.     ENDPROC _dataseg
  83.  
  84. ;-----------------------------------------------------------------
  85. ; WORD codeseg ();
  86. ; Returns the current value of the CS register.
  87. ;-----------------------------------------------------------------
  88.  
  89.     public _codeseg
  90.     STARTPROC _codeseg
  91.  
  92.     mov    ax,cs
  93.     ret
  94.  
  95.     ENDPROC _codeseg
  96.  
  97. ;-----------------------------------------------------------------
  98. ; void far_setmem (seg, offs, length, value);
  99. ;    WORD seg, offs;
  100. ;    UWORD length;
  101. ;    WORD value;
  102. ; Set length bytes starting at seg:offs to value.
  103. ; NOTE: This could be optimized by using stosw if possible.
  104. ;-----------------------------------------------------------------
  105.  
  106.     public _far_setmem
  107.     STARTPROC _far_setmem
  108.  
  109.     push    bp
  110.     mov    bp,sp
  111.     push    es
  112.     push    si
  113.     push    di
  114.  
  115.     mov    es,ARGB[bp]    ; segment
  116.     mov    di,ARGB+2[bp]    ; offset
  117.     mov    cx,ARGB+4[bp]    ; count
  118.     mov    al,ARGB+6[bp]    ; value
  119.     jcxz    far_setmem_done
  120.     cld
  121.     rep    stosb
  122. far_setmem_done:
  123.     pop    di
  124.     pop    si
  125.     pop    es
  126.     pop    bp
  127.     ret
  128.  
  129.     ENDPROC _far_setmem
  130.  
  131. ;-----------------------------------------------------------------
  132. ; void far_movmem (sseg, soffs, dseg, doffs, length);
  133. ;    WORD sseg, soffs, dseg, doffs;
  134. ;    UWORD length;
  135. ; Move length bytes starting at sseg:soffs to dseg:doffs.
  136. ; This proc doesn't handle overlapping source & dest.
  137. ; NOTE: Could speed this up by using WORD move!
  138. ;-----------------------------------------------------------------
  139.  
  140.     public _far_movmem
  141.     STARTPROC _far_movmem
  142.  
  143.     push    bp
  144.     mov    bp,sp
  145.     push    ds
  146.     push    es
  147.     push    si
  148.     push    di
  149.  
  150.     mov    ds,ARGB[bp]    ; source seg
  151.     mov    si,ARGB+2[bp]    ; source offs
  152.     mov    es,ARGB+4[bp]    ; dest seg
  153.     mov    di,ARGB+6[bp]    ; dest offs
  154. mov0:
  155.     mov    cx,ARGB+8[bp]    ; # bytes
  156.     jcxz    far_movmem_done
  157. move_left_to_right:
  158.     cld
  159.     rep    movsb
  160. far_movmem_done:
  161.     pop    di
  162.     pop    si
  163.     pop    es
  164.     pop    ds
  165.     pop    bp
  166.     ret
  167.  
  168.     ENDPROC _far_movmem
  169.  
  170. ;-----------------------------------------------------------------
  171. ; void far_movmem_same_seg(UWORD seg, UWORD soffs, UWORD doffs, UWORD length);
  172. ; Move length bytes starting at seg:soffs to seg:doffs,
  173. ; dealing with possible OVERLAP --
  174. ; when destination starts AFTER source, move RIGHT-TO-LEFT.
  175. ; NOTE: Could speed this up by using WORD move!
  176. ; NOTE: must have same register push/pop sequence as "_far_movmem".
  177. ;-----------------------------------------------------------------
  178.  
  179.     public _far_movmem_same_seg
  180.     STARTPROC _far_movmem_same_seg
  181.  
  182.     push    bp
  183.     mov    bp,sp
  184.     push    ds
  185.     push    es
  186.     push    si
  187.     push    di
  188.  
  189.     mov    ds,ARGB[bp]    ; source seg
  190.     mov    si,ARGB+2[bp]    ; source offs
  191.     mov    es,ARGB[bp]    ; dest seg
  192.     mov    di,ARGB+4[bp]    ; dest offs
  193.     mov    cx,ARGB+6[bp]    ; # bytes
  194.     jcxz    far_movmem_same_seg_done
  195.  
  196.     cmp    di,si
  197.     jbe    move_left_to_right
  198.  
  199.     std            ; Backwards through memory.
  200.     add    si,cx
  201.     dec    si        ; Address of last byte.
  202.     add    di,cx
  203.     dec    di        ; Address of last byte.
  204.     rep    movsb
  205. far_movmem_same_seg_done:
  206.     cld
  207.     pop    di
  208.     pop    si
  209.     pop    es
  210.     pop    ds
  211.     pop    bp
  212.     ret
  213.  
  214.     ENDPROC _far_movmem_same_seg
  215.  
  216. ;-----------------------------------------------------------------
  217. ; void far_swapmem (sseg, soffs, dseg, doffs, length);
  218. ;    WORD sseg, soffs, dseg, doffs;
  219. ;    UWORD length;
  220. ; Swap length bytes starting at sseg:soffs with dseg:doffs.
  221. ; This proc doesn't handle overlapping source & dest.
  222. ; NOTE: Could speed this up by using WORD operations! (and by using xchg)
  223. ;-----------------------------------------------------------------
  224.  
  225.     public _far_swapmem
  226.     STARTPROC _far_swapmem
  227.  
  228.     push    bp
  229.     mov    bp,sp
  230.     push    ds
  231.     push    es
  232.     push    si
  233.     push    di
  234.  
  235.     mov    ds,ARGB[bp]    ; source seg
  236.     mov    si,ARGB+2[bp]    ; source offs
  237.     mov    es,ARGB+4[bp]    ; dest seg
  238.     mov    di,ARGB+6[bp]    ; dest offs
  239.     mov    cx,ARGB+8[bp]    ; # bytes
  240.     jcxz    far_swapmem_done
  241.     cld
  242. swap_loop:
  243.     mov    al,[si]
  244.     mov    bl,es:[di]
  245.     mov    [si],bl
  246.     mov    es:[di],al
  247.     inc    si
  248.     inc    di
  249.     loop    swap_loop
  250. far_swapmem_done:
  251.     pop    di
  252.     pop    si
  253.     pop    es
  254.     pop    ds
  255.     pop    bp
  256.     ret
  257.  
  258.     ENDPROC _far_swapmem
  259.  
  260. ;-----------------------------------------------------------------
  261. ; LongFrac LFMULT (a, b);
  262. ;    LongFrac a, b;
  263. ; Multiply two long fractions (ie, 32-bit fixed point numbers with 16 bits
  264. ; of binary fraction).
  265. ;
  266. ; register usage:
  267. ;    [bp+ARGB]    a.low
  268. ;    [bp+ARGB+2]    a.hi
  269. ;    [bp+ARGB+4]    b.lo
  270. ;    [bp+ARGB+6]    b.hi
  271. ;    ax,dx = result (lo,hi)
  272. ;-----------------------------------------------------------------
  273.  
  274.     public _LFMULT
  275.     STARTPROC _LFMULT
  276.  
  277.     push    bp
  278.     mov    bp,sp
  279.     push    di
  280.     push    si
  281.     xor    si,si
  282.     mov    ax,[bp+ARGB+2]
  283.     test    ax,ax            ; a>0 ?
  284.     jns    aplus
  285.     not    word ptr [bp+ARGB+2]    ; a = -a
  286.     neg    word ptr [bp+ARGB]
  287.     sbb    word ptr [bp+ARGB+2],0ffffh
  288.     not    si
  289. aplus:    mov    ax,[bp+ARGB+6]
  290.     test    ax,ax            ; b>0?
  291.     jns    bplus
  292.     not    word ptr [bp+ARGB+6]    ; b = -b
  293.     neg    word ptr [bp+ARGB+4]
  294.     sbb    word ptr [bp+ARGB+6],0ffffh
  295.     not    si
  296. bplus:    mov    ax,[bp+ARGB]        ; get a.lo
  297.     mul    word ptr [bp+ARGB+4]    ; a.lo*b.lo
  298.     mov    bx,dx            ; res.lo = highhalf(a.lo*b.lo)
  299.     mov    ax,[bp+ARGB+2]
  300.     mul    word ptr [bp+ARGB+6]; a.hi*b.hi
  301.     mov    cx,ax            ; res.hi = lowhalf(a.hi*b.hi)
  302.     mov    ax,[bp+ARGB]
  303.     mul    word ptr [bp+ARGB+6]    ; a.lo*b.hi
  304.     add    bx,ax
  305.     adc    cx,dx
  306.     mov    ax,[bp+ARGB+2]
  307.     mul    word ptr [bp+ARGB+4]    ; a.hi*b.lo
  308.     add    ax,bx            ; ax = lo
  309.     adc    dx,cx            ; dx = hi
  310.     test    si,si
  311.     jns    leave            ; if (neg)
  312.     not    dx            ; res = -res
  313.     neg    ax
  314.     sbb    dx,0ffffh
  315. leave:
  316.     pop si
  317.     pop    di
  318.     pop    bp
  319.     ret
  320.  
  321.     ENDPROC _LFMULT
  322.  
  323. ;-----------------------------------------------------------------
  324. ; Return TRUE if there is a char in the keyboard buffer, or FALSE otherwise.
  325. ;-----------------------------------------------------------------
  326.  
  327.     public _char_avail
  328.     STARTPROC _char_avail
  329.  
  330.     mov    ah,1
  331.     int    16h
  332.     jz    no_char_avail
  333.     mov    ax,-1
  334.     ret
  335. no_char_avail:
  336.     xor    ax,ax
  337.     ret
  338.  
  339.     ENDPROC _char_avail
  340.  
  341. ;-----------------------------------------------------------------
  342. ; Get an "extended" char, where normal chars are in the range 0-255, and
  343. ; non-ascii chars (for example, the function keys) are >= 256.
  344. ;-----------------------------------------------------------------
  345.  
  346.     public _get_char
  347.     STARTPROC _get_char
  348.  
  349.     mov    ah,0
  350.     int    16h
  351.     or    al,al
  352.     jz    gc_done
  353.     xor    ah,ah
  354. gc_done:
  355.     ret
  356.  
  357.     ENDPROC _get_char
  358.  
  359. ;-----------------------------------------------------------------
  360. ; set_ioError: if an io or critical error occurred, squirrels 
  361. ; away the error code and clears did_crit_error and returns -1
  362. ;
  363. ; Assumes that the carry flag and ax are the results of the last
  364. ; io operation (int 21h).
  365. ;
  366. ; If no error occurred, ax is unchanged.
  367. ;-----------------------------------------------------------------
  368. did_crit_error    dw 0    ;NOTE: didn't include crit error handler in program.
  369.  
  370.     STARTPROC set_ioError
  371.     pushf                ; hold carry flag
  372.  
  373.     test     cs:did_crit_error, 0ffffh
  374.     jz    noCritError
  375.     push    cs:did_crit_error      
  376.     pop    _ioError
  377.  
  378.     popflags
  379.     jmp    short ioerr
  380.  
  381. noCritError:
  382.     popflags
  383.     jnc    iodone            ; okay; leave ax unchanged
  384.     mov    _ioError,ax
  385. ioerr:
  386.     mov    cs:did_crit_error,0
  387.     mov    ax,0ffffh        ; return -1 for any error
  388. iodone:    ret
  389.     ENDPROC set_ioError
  390.  
  391. ;-----------------------------------------------------------------
  392. ; Open Dos File: fileHandle = opendos (name, access);
  393. ;-----------------------------------------------------------------
  394.  
  395.     public _opendos
  396.     STARTPROC _opendos
  397.  
  398.     push    bp
  399.     mov    bp,sp
  400.     mov    al,[bp+ARGB+2]    ; get access code
  401.     mov    dx,[bp+ARGB]    ; pointer to name
  402.     mov    ah,03dh
  403.     int    021h
  404.     call    set_ioError
  405.      pop    bp
  406.     ret
  407.  
  408.     ENDPROC _opendos
  409.  
  410. ;-----------------------------------------------------------------
  411. ; Create Dos File: fileHandle = creatdos (name);
  412. ;-----------------------------------------------------------------
  413.  
  414.     public _creatdos
  415.     STARTPROC _creatdos
  416.  
  417.     push    bp
  418.     mov    bp,sp
  419.     xor    cx,cx        ; attribute= normal files
  420.     mov    dx,[bp+ARGB]    ; pointer to name
  421.     mov    ah,03ch
  422.     int    021h        ; do open or create
  423.  
  424.     jnb    cdx        ; if carry flag is set
  425.     mov    ax,0FFFFh    ;    return -1
  426. cdx:
  427.     pop    bp
  428.     ret
  429.  
  430.     ENDPROC _creatdos
  431.  
  432. ;-----------------------------------------------------------------
  433. ; Close Dos File: closedos (filehandle);
  434. ;-----------------------------------------------------------------
  435.  
  436.     public _closedos
  437.     STARTPROC _closedos
  438.  
  439.     push    bp
  440.     mov    bp,sp
  441.     mov    bx,[bp+ARGB]    ; get file handle
  442.     mov    ah,03eh
  443.     int    021h        ; do read or write
  444.     pop    bp
  445.     ret
  446.  
  447.     ENDPROC _closedos
  448.  
  449. ;----------------------------------------------------------------------
  450. ; Delete Dos File: deletedos (name);  
  451. ;---------------------------------------------------------------------
  452.  
  453.     public _deletedos
  454.     STARTPROC _deletedos
  455.  
  456.     push    bp
  457.     mov    bp,sp
  458.     mov    dx,ARGB[bp]    ; pointer to name
  459.     mov    ah,41h
  460.     int    21h        ; delete file
  461.     call    set_ioError
  462.     pop    bp
  463.     ret
  464.  
  465.     ENDPROC _deletedos
  466.  
  467. ;-----------------------------------------------------------------
  468. ; Read from Dos File: nBytes = readdos (file, seg, offset, length);
  469. ;-----------------------------------------------------------------
  470.  
  471. O_FILE        = ARGB
  472. O_SEG        = ARGB+2
  473. O_OFFSET    = ARGB+4
  474. O_LENGTH    = ARGB+6
  475.  
  476.     public _readdos
  477.     STARTPROC _readdos
  478.  
  479.     push    bp
  480.     mov    bp,sp
  481.     push    ds
  482.     mov    ah,3fh
  483.     mov    bx,O_FILE[bp]
  484.     mov    cx,O_LENGTH[bp]
  485.     mov    ds,O_SEG[bp]
  486.     mov    dx,O_OFFSET[bp]
  487.     int    021h
  488.     call    set_ioError
  489.     pop    ds
  490.      pop    bp
  491.     ret
  492.  
  493.     ENDPROC _readdos
  494.  
  495. ;-----------------------------------------------------------------
  496. ; Write to Dos File: nBytes = writedos (file, seg, offset, length);
  497. ; RETURN -1 on error.
  498. ;-----------------------------------------------------------------
  499.  
  500. O_FILE        = ARGB
  501. O_SEG        = ARGB+2
  502. O_OFFSET    = ARGB+4
  503. O_LENGTH    = ARGB+6
  504.  
  505.     public _writedos
  506.     STARTPROC _writedos
  507.  
  508.     push    bp
  509.     mov    bp,sp
  510.     push    ds
  511.     mov    ah,40h
  512.     mov    bx,O_FILE[bp]
  513.     mov    cx,O_LENGTH[bp]
  514.     mov    ds,O_SEG[bp]
  515.     mov    dx,O_OFFSET[bp]
  516.     int    021h
  517.     call    set_ioError
  518.     pop    ds
  519.      pop    bp
  520.     ret
  521.  
  522.     ENDPROC _writedos
  523.  
  524. ;-----------------------------------------------------------------
  525. ; LFDIV (num, denom);
  526. ;-----------------------------------------------------------------
  527.  
  528. NUM    =    ARGB
  529. DENOM    =    ARGB+4
  530.  
  531.     public _LFDIV
  532.     STARTPROC _LFDIV
  533.  
  534.     push    bp
  535.     mov    bp,sp
  536.  
  537. ; neg = FALSE
  538.     xor    cx,cx
  539.  
  540. ; if (num < 0) { num = -num; neg = !neg; }
  541.     cmp    word ptr NUM+2[bp],0
  542.     jge    lfdiv1
  543.     mov    ax,NUM[bp]        ; num = -num
  544.     mov    dx,NUM+2[bp]
  545.     neg    ax
  546.     adc    dx,0
  547.     neg    dx
  548.     mov    NUM[bp],ax
  549.     mov    NUM+2[bp],dx
  550.     not    cx            ; neg = !neg
  551. lfdiv1:
  552.  
  553. ; if (denom < 0) { denom = -denom; neg = !neg; }
  554.     cmp    word ptr DENOM+2[bp],0
  555.     jge    lfdiv2
  556.     mov    ax,DENOM[bp]        ; denom = -denom
  557.     mov    dx,DENOM+2[bp]
  558.     neg    ax
  559.     adc    dx,0
  560.     neg    dx
  561.     mov    DENOM[bp],ax
  562.     mov    DENOM+2[bp],dx
  563.     not    cx            ; neg = !neg
  564. lfdiv2:
  565.  
  566. ; while (denom >= 0x10000) { num >>= 1; denom >>= 1; }
  567.     mov    bx,cx            ; save neg in bx
  568. lfdiv5:
  569.     mov    cx,DENOM+2[bp]
  570.     jcxz    lfdiv3
  571.     sar    word ptr NUM+2[bp],1    ; num >>= 1
  572.     rcr    word ptr NUM[bp],1
  573.     sar    word ptr DENOM+2[bp],1    ; denom >>= 1
  574.     rcr    word ptr DENOM[bp],1
  575.     jmp    lfdiv5
  576. lfdiv3:
  577.     mov    cx,bx            ; restore neg to cx
  578.  
  579. ; high word of result = num / denom
  580.     mov    ax,NUM[bp]
  581.     mov    dx,NUM+2[bp]
  582.     cmp    dx,DENOM[bp]        ; test for overflow
  583.     jb    no_overflow
  584.     mov    ax,7fffh        ; overflow, so use a large #
  585.     xor    dx,dx
  586.     jmp    lfdiv6
  587. no_overflow:
  588.     div    word ptr DENOM[bp]
  589.     mov    bx,ax
  590.  
  591. ; low word of result = ((num % denom) << 16) / denom
  592. lfdiv6:
  593.     xor    ax,ax
  594.     div    word ptr DENOM[bp]
  595.     mov    dx,bx            ; dx = high word of result
  596.  
  597. ; if (neg) result = -result;
  598.     jcxz    lfdiv4
  599.     neg    ax
  600.     adc    dx,0
  601.     neg    dx
  602. lfdiv4:
  603.  
  604.     pop    bp
  605.     ret
  606.  
  607.     ENDPROC _LFDIV
  608.  
  609. ;-----------------------------------------------------------------
  610. ; WORD get_first_mcb ();
  611. ; Returns address of first MCB in DOS free memory list.
  612. ;-----------------------------------------------------------------
  613.  
  614.     public _get_first_mcb
  615.     STARTPROC _get_first_mcb
  616.  
  617.     mov    ah,52h
  618.     int    21h
  619.     mov    ax,es:[bx-2]
  620.     ret
  621.  
  622.     ENDPROC _get_first_mcb
  623.  
  624. ;-----------------------------------------------------------------
  625. ; WORD cdist (a, b);
  626. ;    LONG a, b;
  627. ; Calculate the distance between RGB color values a and b.  This is
  628. ; done using the sum of the absolute R,G,B deltas.  It would be more
  629. ; accurate (but much slower) to calculate the actual distance between them.
  630. ;
  631. ; Improved: absdR + absdG + absdB + MAX(absdR, absdG, absdB).
  632. ; This approximates the sum of squares, by forcing large component to
  633. ; have double contribution to error term.
  634. ;-----------------------------------------------------------------
  635.  
  636. A    = ARGB
  637. B    = ARGB+4
  638.  
  639.     public _cdist
  640.     STARTPROC _cdist
  641.  
  642.     push    bp
  643.     mov    bp,sp
  644.  
  645. ; --- clear top half of ax so we can use it as a word
  646.     sub    ah,ah
  647.  
  648. ; --- get absolute distance between BLUE coords, put result in bx
  649.     mov    bl,A[bp]
  650.     mov    cl,B[bp]
  651.     cmp    bl,cl
  652.     jae    cdist_p1
  653.     xchg    bl,cl
  654. cdist_p1:
  655.     sub    bl,cl
  656.     sub    bh,bh        ; BX: abs(delta R).
  657.  
  658.     mov    dx,bx        ; dx will be MAX.
  659.  
  660. ; --- get absolute distance between GREEN coords, add to bx
  661.     mov    al,A+1[bp]
  662.     mov    cl,B+1[bp]
  663.     cmp    al,cl
  664.     jae    cdist_p2
  665.     xchg    al,cl
  666. cdist_p2:
  667.     sub    al,cl
  668.     add    bx,ax        ; BX: absdR + absdG.
  669.  
  670.     cmp    dx,ax
  671.     jge    cdist_R_ge_G
  672.     mov    dx,ax
  673. cdist_R_ge_G:            ; DX: MAX(absdR, absdG).
  674.  
  675. ; --- get absolute distance between RED coords, add bx to this value
  676.     mov    al,A+2[bp]
  677.     mov    cl,B+2[bp]
  678.     cmp    al,cl
  679.     jae    cdist_p3
  680.     xchg    al,cl
  681. cdist_p3:
  682.     sub    al,cl
  683.     add    ax,bx        ; AX: absdR + absdG + absdB.
  684.  
  685.     cmp    dx,ax
  686.     jge    cdist_RG_ge_B
  687.     mov    dx,ax
  688. cdist_RG_ge_B:            ; DX: MAX(absdR, absdG, absdB).
  689.  
  690.     add    ax,dx        ; AX: absdR + absdG + absdB + MAX(...).
  691.  
  692.     pop    bp
  693.     ret
  694.  
  695.     ENDPROC _cdist
  696.  
  697. ;-----------------------------------------------------------------
  698. ; void dos_print_string (string);
  699. ;    char *string;
  700. ; Call DOS to print the given string, in text mode.  The string should
  701. ; not contain a '$', since DOS will treat that as the end of the string,
  702. ; and not print any chars after that!
  703. ;-----------------------------------------------------------------
  704.  
  705.     public _dos_print_string
  706.     STARTPROC _dos_print_string
  707.  
  708.     push    bp
  709.     mov    bp,sp
  710.     push    si
  711.  
  712. ; --- replace the NULL terminator with a '$', like DOS wants
  713.     mov    si,ARGB[bp]
  714.     dec    si
  715. find_dollar:
  716.     inc    si
  717.     mov    al,[si]
  718.     or    al,al
  719.     jnz    find_dollar
  720.     mov    byte ptr [si],'$'
  721.  
  722. ; --- call DOS to print the string
  723.     push    si
  724.     mov    ah,9
  725.     mov    dx,ARGB[bp]
  726.     int    21h
  727.     pop    si
  728.  
  729. ; --- restore NULL string terminator
  730.     mov    byte ptr [si],0
  731.  
  732.     pop    si
  733.     pop    bp
  734.     ret
  735.  
  736.     ENDPROC _dos_print_string
  737.  
  738. ;-----------------------------------------------------------------
  739. ; Allocate Memory:  segment = allocsome (paragraphs, &size)
  740. ; Will allocate request or largest remaining, whichever is bigger.
  741. ; Returns segment = 0 if failed.  Puts number of paragraphs actually
  742. ; allocated into *size.
  743. ; Right now, this is only used by FixTandyMemory.
  744. ;-----------------------------------------------------------------
  745.  
  746.     public _allocsome
  747.     STARTPROC _allocsome
  748.  
  749.     push    bp
  750.     mov    bp,sp
  751.     mov    bx,[bp+ARGB]
  752. allocscont:
  753.     mov    di,[bp+ARGB+2]
  754.     mov    [di],bx     ; return number of words allocated
  755.     mov    ax,0
  756.     cmp    ax,bx
  757.     je    allocsret    ; fail nothing requested
  758.     mov    ax,04800h
  759.     int    021h        ; execute DOS function
  760.     jnc    allocsret
  761.     mov    cx,ax
  762.     mov    ax,0        ; error: return NIL
  763.     cmp    cx,7        ; arena trashed
  764.     jne    allocscont    ; keep trying until we alloc max left or fail
  765. allocsret:
  766.     pop    bp
  767.     ret
  768.  
  769.     ENDPROC _allocsome
  770.  
  771. ;-----------------------------------------------------------------
  772. ; LONG FreeDiskSpace (drive);
  773. ;    WORD drive; /* 0 = drive A, 1 = drive B, etc... */
  774. ; Returns free disk space in bytes on the specified drive.  If there
  775. ; is an error accessing that drive, it returns 0.
  776. ;-----------------------------------------------------------------
  777.  
  778.     public _FreeDiskSpace
  779.     STARTPROC _FreeDiskSpace
  780.  
  781.     push    bp
  782.     mov    bp,sp
  783.  
  784.     mov    ah,36h
  785.     mov    dl,ARGB[bp]
  786.     inc    dl        ; this func uses 1 = drive A, 2 = drive B...
  787.     int    21h
  788.     cmp    ax,0ffffh
  789.     jne    fds_no_error
  790. ; --- error getting info, so return 0
  791.     xor    ax,ax
  792.     xor    dx,dx
  793.     jmp    fds_done
  794. ; --- no error, so return (sectorsPerCluster * bytesPerSector * freeClusters)
  795. ; NOTE: we assume that sectorsPerCluster * bytesPerSector < 64k.
  796. fds_no_error:
  797.     mul    cx
  798.     mul    bx
  799. fds_done:
  800.     pop    bp
  801.     ret
  802.  
  803.     ENDPROC _FreeDiskSpace
  804.  
  805. ;-----------------------------------------------------------------
  806. ; LONG GetSystemTime ();
  807. ; Returns the number of timer ticks (18.2 per second) since midnight.
  808. ;-----------------------------------------------------------------
  809.  
  810.     public _GetSystemTime
  811.     STARTPROC _GetSystemTime
  812.  
  813.     mov    ah,0
  814.     int    1ah
  815.     mov    ax,dx        ; move low word to ax
  816.     mov    dx,cx        ; move high word to dx
  817.     ret
  818.  
  819.     ENDPROC _GetSystemTime
  820.  
  821. ;-----------------------------------------------------------------
  822. ; name        WordMulDiv --
  823. ;
  824. ; c = (a*num)/denom;
  825. ;
  826. ; UWORD muldiv(a,num,denom)  UWORD a,num,denom;
  827. ;
  828. ;  register usage
  829. ;        [bp+ARGB]    a
  830. ;        [bp+ARGB+2]    num
  831. ;        [bp+ARGB+4]    denom
  832. ;-----------------------------------------------------------------
  833.  
  834.     public _WordMulDiv
  835.     STARTPROC _WordMulDiv
  836.     push    bp
  837.     mov    bp,sp
  838.     mov ax,[bp+ARGB]
  839.     mul    word ptr[bp+ARGB+2]
  840.     div word ptr[bp+ARGB+4]
  841.     pop    bp
  842.     ret
  843.     ENDPROC _WordMulDiv
  844.  
  845. ;-----------------------------------------------------------------
  846.  
  847.     ENDPS misca
  848.     END
  849.